package com.unitd.frame.sso.common.encrypt;

import com.unitd.frame.sso.common.config.SSOConfig;
import com.unitd.frame.comm.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * @desc MD5加密工具类
 * @filename MD5.java
 * @copyright www.pactera.com.cn
 * @author Hudan
 * @version 1.0
 * @date 2016/10/27
 */
public class MD5 {

	private static final Logger logger = LoggerFactory.getLogger(MD5.class.getName());
	public static final String ALGORITHM = "MD5";

	/**
	 * @desc 字符串加密为MD5 中文加密一致通用,必须转码处理： plainText.getBytes("UTF-8")
	 * @param plainText 需要加密的字符串
	 * @return String
	 */
	public static String toMD5(String plainText) {
		StringBuilder rlt = new StringBuilder();
		try {
			rlt.append(md5String(plainText.getBytes(SSOConfig.getSSOEncoding())));
		} catch (UnsupportedEncodingException e) {
			logger.error("将字符串进行MD5加密失败:" + e);
			e.printStackTrace();
		}
		return rlt.toString();
	}

	/**
	 * @desc MD5 参数签名生成算法
	 * @param params 请求参数集,所有参数必须已转换为字符串类型
	 * @param secret 签名密钥
	 * @return 签名
	 */
	public static String getSignature(HashMap<String, String> params, String secret) {
		Map<String, String> sortedParams = new TreeMap<>(params);
		Set<Entry<String, String>> entrys = sortedParams.entrySet();
		StringBuilder basestring = new StringBuilder();
		for (Entry<String, String> param : entrys) {
			basestring.append(param.getKey()).append("=").append(param.getValue());
		}
		return getSignature(basestring.toString(), secret);
	}

	/**
	 * @desc MD5 参数签名生成算法
	 * @param sigstr 签名字符串
	 * @param secret 签名密钥
	 * @return 签名
	 */
	public static String getSignature(String sigstr, String secret) {
		StringBuilder basestring = new StringBuilder(sigstr);
		basestring.append("#");
		basestring.append(toMD5(secret));
		return toMD5(basestring.toString());
	}

	/**
	 * @desc 对字节数组进行MD5加密预处理
	 * @param data 字节数组
	 * @return
	 */
	public static byte[] md5Raw(byte[] data) {
		byte[] md5buf = null;
		try {
			MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);
			md5buf = md5.digest(data);
		} catch (Exception e) {
			md5buf = null;
			logger.error("对字节数组进行MD5加密预处理失败:" + e);
			e.printStackTrace();
		}
		return md5buf;
	}

	/**
	 * @desc 对字节数组进行MD5加密预处理
	 * @param data 字节数组
	 * @return
	 */
	public static String md5String(byte[] data) {
		String md5Str = "";
		try {
			MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);
			byte[] buf = md5.digest(data);
			for (int i = 0; i < buf.length; i++) {
				md5Str += ByteUtils.byte2Hex(buf[i]);
			}
		} catch (Exception e) {
			md5Str = null;
			logger.error("对字节数组进行MD5加密预处理失败:" + e);
			e.printStackTrace();
		}
		return md5Str;
	}
}